package com.quanyan.club.util.qrcode;

import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.quanyan.club.util.qrcode.util.CodeColor;
import com.quanyan.club.util.qrcode.util.CodeConfig;
import com.quanyan.club.util.qrcode.util.CodeResolve;
import com.quanyan.club.util.qrcode.util.LogoConfig;
import sun.misc.BASE64Decoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 二维码生成google zxing
 *
 * @author xian-guo
 */
public class ZXingCodeUtil {

    /**
     * 设置二维码的格式参数
     *
     * @return
     */
    public Map getDecodeHintType() {
        Map hints = new HashMap();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 0);
        hints.put(EncodeHintType.MAX_SIZE, 350);
        hints.put(EncodeHintType.MIN_SIZE, 100);
        return hints;
    }

    /**
     * 二维码图片添加Logo
     *
     * @param bim        图片流
     * @param logoConfig Logo图片设置参数
     * @throws Exception 异常上抛
     */
    private void addLogo_QRCode(BufferedImage bim, String imgStr,
                                LogoConfig logoConfig) throws Exception {
        try {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] b = decoder.decodeBuffer(imgStr);
            ByteArrayInputStream in = new ByteArrayInputStream(b);
            BufferedImage image = bim;
            Graphics2D g = image.createGraphics();
            BufferedImage logo = ImageIO.read(in);
//            logo = ImageUtils.zoomImage(logo,logoConfig.getLogoSize());
//            int widthLogo=logo.getWidth();
//            int heightLogo=logo.getHeight();
            int logoSize=logoConfig.getLogoSize();
            int widthLogo = logo.getWidth(null) > image.getWidth() * logoSize
                    / 100 ? (image.getWidth() * logoSize / 100) : logo
                    .getWidth(null);
            int heightLogo = logo.getHeight(null) > image
                    .getHeight() * logoSize / 100 ? (image.getHeight()
                    * logoSize / 100) : logo.getWidth(null);
            int x = (image.getWidth() - widthLogo) / 2;
            int y = (image.getHeight() - heightLogo) / 2;
            g.drawImage(logo, x, y, widthLogo, heightLogo, null);
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            g.setStroke(new BasicStroke(logoConfig.getBorder()));
            g.setColor(logoConfig.getBorderColor());
            g.drawRect(x, y, widthLogo, heightLogo);
            g.dispose();
            in.close();
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * 设置二维码边框
     *
     * @param codeConfig
     * @param bim
     * @param backPic
     * @throws IOException
     */
    private void setCodeBorder(CodeConfig codeConfig, BufferedImage bim,
                               File backPic) throws IOException {
        BufferedImage image = bim;
        Graphics2D g = image.createGraphics();
        g.setStroke(new BasicStroke(codeConfig.getCodeBorderSize()));
        g.setColor(codeConfig.getCodeBorderColor());
        g.drawRect(0, 0, image.getWidth(), image.getHeight());
        g.dispose();
        image.flush();
    }

    /**
     * 二维码的解析
     *
     * @param image 图片文件流
     * @return 解析后的Result结果集
     * @throws Exception 错误异常上抛
     */
    public Result parseQR_CODEImage(BufferedImage image) throws Exception {
        Result result = null;
        try {
            MultiFormatReader formatReader = new MultiFormatReader();
            LuminanceSource source = new CodeResolve(image);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
            Map hints = new HashMap();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            result = formatReader.decode(binaryBitmap, hints);
            System.out.println("resultFormat =" + result.getBarcodeFormat());
            System.out.println("resultText =" + result.getText());
        } catch (Exception e) {
            throw e;
        }
        return result;
    }

    /**
     * 生成二维码bufferedImage图片
     *
     * @param codeConfig 二维码配置信息
     * @return 生成后的 BufferedImage
     * @throws Exception 异常上抛
     */
    public BufferedImage getQR_CODEBufferedImage(CodeConfig codeConfig)
            throws Exception {
        MultiFormatWriter multiFormatWriter = null;
        BitMatrix bm = null;
        BufferedImage image = null;
        try {
            multiFormatWriter = new MultiFormatWriter();
            bm = multiFormatWriter.encode(codeConfig.getContent(),
                    codeConfig.getBarcodeformat(), codeConfig.getWidth(),
                    codeConfig.getHeight(), codeConfig.getHints());
            int w = bm.getWidth();
            int h = bm.getHeight();
            int[] pixels = new int[w * h];
            for (int x = 0; x < w; x++) {
                for (int y = 0; y < h; y++) {
                    // image.setRGB(x, y, bm.get(x, y) ?
                    // codeConfig.getCodeColor()
                    // .getBlackColor().getRGB() : codeConfig
                    // .getCodeColor().getWhiteColor().getRGB());

                    pixels[x * h + y] = bm.get(x, y) ? codeConfig
                            .getCodeColor().getBlackColor().getRGB()
                            : codeConfig.getCodeColor().getWhiteColor()
                            .getRGB();
                }
            }
            image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
            image.getRaster().setDataElements(0, 0, w, h, pixels);
            if (codeConfig.isLogoFlag()) {
                this.addLogo_QRCode(image, codeConfig.getLogoPath(),
                        codeConfig.getLogoConfig());
            }
            if (codeConfig.isCodeBorderFlag()) {
                this.setCodeBorder(codeConfig, image, null);
            }
        } catch (WriterException e) {
            throw e;
        }
        return image;
    }

    public static void main(String[] args) throws WriterException {
        String content = "http://www.baidu.com";
        System.out.println("inputParam:" + content);
        try {
            // 生成二维码
            File file = new File("G:/Michael_QRCode.png");
            ZXingCodeUtil zp = new ZXingCodeUtil();
            CodeConfig zxingconfig = new CodeConfig();
            zxingconfig.setHints(zp.getDecodeHintType());
            zxingconfig.setContent(content);
            zxingconfig.setLogoPath(ImageUtils.larkLogo);
            zxingconfig.setLogoConfig(new LogoConfig());
            zxingconfig.setLogoFlag(true); // 设置生成Logo图片
            zxingconfig.setCodeColor(new CodeColor(Color.BLACK, Color.WHITE));//设置二维码颜色
            BufferedImage bim = zp.getQR_CODEBufferedImage(zxingconfig);// 生成二维码
            ImageIO.write(bim, "png", file); // 图片写出
//            Thread.sleep(500); // 缓冲
//            zp.parseQR_CODEImage(bim); // 解析调用
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}